/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Logger } from '../..';
import { ITargetContext } from '../../../json-plugin/interfaces/ITargetContext';
import SerializationPathUtil from '../../utils/SerializationPathUtil';

/**
 * build-profile.json5 配置更新服务实现
 */
export class BuildProfileUpdaterImpl {

  updateSourceRoots(targetContext: ITargetContext): void {
    try {
      // 获取模块根目录和 build-profile.json5 路径
      const moduleRoot = this.getModuleRootFromContext(targetContext);
      const buildProfilePath = SerializationPathUtil.join(moduleRoot, 'build-profile.json5');

      Logger.debug(`准备更新 build-profile.json5: ${buildProfilePath}`);

      if (!SerializationPathUtil.exist(buildProfilePath)) {
        Logger.warn(`build-profile.json5 文件不存在: ${buildProfilePath}`);
        return;
      }

      // 读取现有配置
      const config = targetContext.context.buildProfileOpt;
      Logger.debug(`当前配置: ${JSON.stringify(config, null, 2)}`);

      // 更新 sourceRoots 配置
      const updated = this.updateSourceRootsConfig(config);

      if (updated) {
        // 写回配置文件
        this.writeBuildProfile(targetContext, buildProfilePath, config);
        Logger.info(`已更新 build-profile.json5 的 sourceRoots 配置: ${buildProfilePath}`);
      } else {
        Logger.debug('sourceRoots 配置无需更新');
      }

    } catch (error) {
      Logger.error(`更新 build-profile.json5 失败: ${error}`);
      throw error;
    }
  }

  /**
   * 从任务上下文获取模块根目录
   */
  private getModuleRootFromContext(context: ITargetContext): string {
    // 通过输出根目录推断模块根目录
    // 输出根目录通常是 moduleName/src/generated
    // 模块根目录应该是 moduleName/
    const outputRoot = context.getOutputRoot();

    // 向上查找包含 build-profile.json5 的目录
    let currentDir = SerializationPathUtil.dirname(outputRoot);

    while (currentDir && currentDir !== SerializationPathUtil.dirname(currentDir)) {
      const buildProfilePath = SerializationPathUtil.join(currentDir, 'build-profile.json5');
      if (SerializationPathUtil.exist(buildProfilePath)) {
        return currentDir;
      }
      currentDir = SerializationPathUtil.dirname(currentDir);
    }

    // 如果找不到，使用输出根目录的父目录的父目录作为fallback
    return SerializationPathUtil.dirname(SerializationPathUtil.dirname(outputRoot));
  }

  /**
   * 读取 build-profile.json5 配置
   */
  private readBuildProfile(buildProfilePath: string): any {
    try {
      // 使用继承自 FileUtil 的方法读取 JSON5
      return SerializationPathUtil.readJson5(buildProfilePath);
    } catch (error) {
      Logger.error(`读取 build-profile.json5 失败: ${buildProfilePath}, 错误: ${error}`);
      throw new Error(`无法读取配置文件: ${buildProfilePath}`);
    }
  }

  /**
   * 写入 build-profile.json5 配置
   */
  private writeBuildProfile(targetContext: ITargetContext, buildProfilePath: string, config: any): void {
    try {
      // 不需要修改源代码，仅重写构建过程中的buildProfile文件，修改源码方式SerializationPathUtil.writeFileSync(buildProfilePath, JSON.stringify(config, null, 2));
      targetContext.context.moduleContext.setBuildProfileOpt(config);
    } catch (error) {
      Logger.error(`写入 build-profile.json5 失败: ${buildProfilePath}, 错误: ${error}`);
      throw new Error(`无法写入配置文件: ${buildProfilePath}`);
    }
  }

  /**
   * 更新 sourceRoots 配置
   * @param config 配置对象
   * @returns 是否进行了更新
   */
  private updateSourceRootsConfig(config: any): boolean {
    let updated = false;
    const generatedSourceRoot = "./src/generated";
    Logger.info(`target.source.sourceRoots start`);

    // 更新 targets 中的 source.sourceRoots
    if (config.targets && Array.isArray(config.targets)) {
      for (const target of config.targets) {
        Logger.info(`target.source.sourceRoots is target: ${target}`);
        if (!target.source) {
          target.source = {};
        }
        if (!target.source.sourceRoots) {
          target.source.sourceRoots = [];
        }

        if (!Array.isArray(target.source.sourceRoots)) {
          Logger.warn('target.source.sourceRoots 不是数组，将重置为数组');
          target.source.sourceRoots = [];
        }

        if (!target.source.sourceRoots.includes(generatedSourceRoot)) {
          target.source.sourceRoots.unshift(generatedSourceRoot);
          Logger.info(`添加 target.source.sourceRoots: ${generatedSourceRoot}`);
          updated = true;
        }
      }
    }

    return updated;
  }
}